From 45268f7ea7829a34b67ec0a83019bc82b6d34bd2 Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:34:56 -0600 Subject: [PATCH] mkshort becomes a class (#1173) * make mkshort a class * add new file mkshort.h * refactor names * use bools with mkshort setters --- CMakeLists.txt | 1 + defs.h | 23 ------ garmin.cc | 44 +++++----- garmin_gpi.cc | 21 ++--- garmin_gpi.h | 5 +- gdb.cc | 36 ++++---- gdb.h | 5 +- gpx.cc | 20 ++--- gpx.h | 3 +- html.cc | 10 ++- html.h | 3 +- humminbird.cc | 74 +++++++++-------- humminbird.h | 5 +- lowranceusr.cc | 9 +- lowranceusr.h | 3 +- main.cc | 13 +-- mkshort.cc | 220 +++++++++++++------------------------------------ mkshort.h | 109 ++++++++++++++++++++++++ nmea.cc | 12 +-- nmea.h | 3 +- ozi.cc | 23 +++--- text.cc | 9 +- text.h | 3 +- tpg.cc | 15 ++-- vcf.cc | 4 - xcsv.cc | 20 ++--- xcsv.h | 24 ++---- 27 files changed, 349 insertions(+), 368 deletions(-) create mode 100644 mkshort.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 12a6c11c4..476883cca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -226,6 +226,7 @@ set(HEADERS legacyformat.h igc.h lowranceusr.h + mkshort.h nmea.h osm.h qstarz_bl_1000.h diff --git a/defs.h b/defs.h index 59529761a..2a337c319 100644 --- a/defs.h +++ b/defs.h @@ -838,29 +838,6 @@ using ff_exit = void (*)(); using ff_writeposn = void (*)(Waypoint*); using ff_readposn = Waypoint* (*)(posn_status*); -/* - * All shortname functions take a shortname handle as the first arg. - * This is an opaque pointer. Callers must not fondle the contents of it. - */ -// This is a crutch until the new C++ shorthandle goes in. - -struct mkshort_handle_imp; // forward declare, definition in mkshort.cc -using short_handle = mkshort_handle_imp*; - -QByteArray mkshort(short_handle, const QByteArray&, bool); -QString mkshort(short_handle, const QString&); -short_handle mkshort_new_handle(); -QString mkshort_from_wpt(short_handle h, const Waypoint* wpt); -void mkshort_del_handle(short_handle* h); -void setshort_length(short_handle, int n); -void setshort_badchars(short_handle, const char*); -void setshort_goodchars(short_handle, const char*); -void setshort_mustupper(short_handle, int n); -void setshort_mustuniq(short_handle, int n); -void setshort_whitespace_ok(short_handle, int n); -void setshort_repeating_whitespace_ok(short_handle, int n); -void setshort_defname(short_handle, const char* s); - #define ARGTYPE_UNKNOWN 0x00000000U #define ARGTYPE_INT 0x00000001U #define ARGTYPE_FLOAT 0x00000002U diff --git a/garmin.cc b/garmin.cc index 976033291..159d3c02d 100644 --- a/garmin.cc +++ b/garmin.cc @@ -51,11 +51,12 @@ #include "jeeps/gpsserial.h" // for DEFAULT_BAUD #include "jeeps/gpsutil.h" // for GPS_User, GPS_Enable_Diagnose, GPS_E... #include "src/core/datetime.h" // for DateTime +#include "mkshort.h" // for MakeShort #define MYNAME "GARMIN" static const char* portname; -static short_handle mkshort_handle; +static MakeShort* mkshort_handle; static GPS_PWay* tx_waylist; static GPS_PWay* tx_routelist; static GPS_PWay* cur_tx_routelist_entry; @@ -75,7 +76,7 @@ static char* baudopt = nullptr; static char* opt_codec = nullptr; static int baud = 0; static int categorybits; -static int receiver_must_upper = 1; +static bool receiver_must_upper = true; static QTextCodec* codec{nullptr}; #define MILITANT_VALID_WAYPT_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" @@ -155,11 +156,11 @@ write_char_string(char* dest, const char* source, size_t destsize) static void rw_init(const QString& fname) { - receiver_must_upper = 1; + receiver_must_upper = true; const char* receiver_charset = "US-ASCII"; if (!mkshort_handle) { - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; } if (global_opts.debug_level > 0) { @@ -218,7 +219,7 @@ rw_init(const QString& fname) } /* - * Grope the unit we're talking to to set setshort_length to + * Grope the unit we're talking to to set set_length to * 20 for the V, * 10 for Street Pilot, (old) Rhino, 76 * 6 for the III, 12, emap, and etrex @@ -260,7 +261,7 @@ rw_init(const QString& fname) case 574: /* Geko 201 */ receiver_short_length = 6; valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " +-"; - setshort_badchars(mkshort_handle, "\"$.,'!"); + mkshort_handle->set_badchars("\"$.,'!"); break; case 155: /* Garmin V */ @@ -270,7 +271,7 @@ rw_init(const QString& fname) break; case 382: /* C320 */ receiver_short_length = 30; - receiver_must_upper = 0; + receiver_must_upper = false; break; case 292: /* (60|76)C[S]x series */ case 421: /* Vista|Legend Cx */ @@ -280,7 +281,7 @@ rw_init(const QString& fname) case 957: /* Legend HC */ receiver_short_length = 14; snwhiteopt = xstrdup("1"); - receiver_must_upper = 0; + receiver_must_upper = false; /* This might be 8859-1 */ receiver_charset = "windows-1252"; break; @@ -288,20 +289,20 @@ rw_init(const QString& fname) case 1095: /* GPS 72H */ receiver_short_length = 10; valid_waypt_chars = MILITANT_VALID_WAYPT_CHARS " +-"; - setshort_badchars(mkshort_handle, "\"$.,'!"); + mkshort_handle->set_badchars("\"$.,'!"); break; case 231: /* Quest */ case 463: /* Quest 2 */ - receiver_must_upper = 0; + receiver_must_upper = false; receiver_short_length = 30; receiver_charset = "windows-1252"; break; case 577: // Rino 530HCx Version 2.50 - receiver_must_upper = 0; + receiver_must_upper = false; receiver_short_length = 14; break; case 429: // Streetpilot i3 - receiver_must_upper = 0; + receiver_must_upper = false; receiver_charset = "windows-1252"; receiver_short_length = 30; break; @@ -332,13 +333,13 @@ rw_init(const QString& fname) * If the user provided a short_length, override the calculated value. */ if (snlen) { - setshort_length(mkshort_handle, xstrtoi(snlen, nullptr, 10)); + mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10)); } else { - setshort_length(mkshort_handle, receiver_short_length); + mkshort_handle->set_length(receiver_short_length); } if (snwhiteopt) { - setshort_whitespace_ok(mkshort_handle, xstrtoi(snwhiteopt, nullptr, 10)); + mkshort_handle->set_whitespace_ok(xstrtoi(snwhiteopt, nullptr, 10)); } /* @@ -346,12 +347,12 @@ rw_init(const QString& fname) * for the new models, we just release this safety check manually. */ if (receiver_must_upper) { - setshort_goodchars(mkshort_handle, valid_waypt_chars); + mkshort_handle->set_goodchars(valid_waypt_chars); } else { - setshort_badchars(mkshort_handle, ""); + mkshort_handle->set_badchars(""); } - setshort_mustupper(mkshort_handle, receiver_must_upper); + mkshort_handle->set_mustupper(receiver_must_upper); /* * This used to mean something when we used cet, but these days this @@ -398,9 +399,8 @@ rw_deinit() } } - if (mkshort_handle) { - mkshort_del_handle(&mkshort_handle); - } + delete mkshort_handle; + mkshort_handle = nullptr; xfree(portname); portname = nullptr; @@ -888,7 +888,7 @@ waypoint_prepare() * mkshort will do collision detection and namespace * cleaning */ - QByteArray ident = mkshort(mkshort_handle, + QByteArray ident = mkshort_handle->mkshort( global_opts.synthesize_shortnames ? str_from_unicode(src) : str_from_unicode(wpt->shortname), diff --git a/garmin_gpi.cc b/garmin_gpi.cc index 473871bb2..793c3c117 100644 --- a/garmin_gpi.cc +++ b/garmin_gpi.cc @@ -1044,7 +1044,7 @@ GarminGPIFormat::enum_waypt_cb(const Waypoint* ref) const auto* wpt = new Waypoint(*ref); if (*opt_unique == '1') { - wpt->shortname = mkshort(short_h, wpt->shortname); + wpt->shortname = short_h->mkshort(wpt->shortname); } wdata_add_wpt(wdata, wpt); @@ -1252,15 +1252,15 @@ GarminGPIFormat::wr_init(const QString& fname) fout = gbfopen_le(fname, "wb", MYNAME); - short_h = mkshort_new_handle(); + short_h = new MakeShort; - setshort_length(short_h, 1024); - setshort_badchars(short_h, "\r\n"); - setshort_mustupper(short_h, 0); - setshort_mustuniq(short_h, 1); - setshort_whitespace_ok(short_h, 1); - setshort_repeating_whitespace_ok(short_h, 0); - setshort_defname(short_h, "POI"); + short_h->set_length(1024); + short_h->set_badchars("\r\n"); + short_h->set_mustupper(false); + short_h->set_mustuniq(true); + short_h->set_whitespace_ok(true); + short_h->set_repeating_whitespace_ok(false); + short_h->set_defname("POI"); codepage = 0; @@ -1325,7 +1325,8 @@ void GarminGPIFormat::wr_deinit() { wdata_free(wdata); - mkshort_del_handle(&short_h); + delete short_h; + short_h = nullptr; gbfclose(fout); if ((opt_sleep) && !gpsbabel_testmode()) { /* don't sleep during 'testo' */ diff --git a/garmin_gpi.h b/garmin_gpi.h index d13920184..5594f6ffc 100644 --- a/garmin_gpi.h +++ b/garmin_gpi.h @@ -55,10 +55,11 @@ #include // for int32_t, int16_t, uint16_t #include // for time_t -#include "defs.h" // for arglist_t, ARG_NOMINMAX, ff_cap, Waypoint, ARGTYPE_BOOL, ARGTYPE_STRING, ff_cap_none, ARGTYPE_FILE, ARGTYPE_INT, bounds, ff_cap_read, ff_cap_write, ff_type, ff_type_file, short_handle +#include "defs.h" // for arglist_t, ARG_NOMINMAX, ff_cap, Waypoint, ARGTYPE_BOOL, ARGTYPE_STRING, ff_cap_none, ARGTYPE_FILE, ARGTYPE_INT, bounds, ff_cap_read, ff_cap_write, ff_type, ff_type_file #include "format.h" // for Format #include "garmin_fs.h" // for garmin_fs_t #include "gbfile.h" // for gbfile +#include "mkshort.h" // for MakeShort class GarminGPIFormat : public Format @@ -377,7 +378,7 @@ private: uint16_t codepage{}; /* code-page, e.g. 1252, 65001 */ reader_data_t* rdata{}; writer_data_t* wdata{}; - short_handle short_h{}; + MakeShort* short_h{}; char units{}; time_t gpi_timestamp = 0; QTextCodec* codec{nullptr}; diff --git a/gdb.cc b/gdb.cc index 347af342f..5efbb55f3 100644 --- a/gdb.cc +++ b/gdb.cc @@ -40,13 +40,14 @@ #include // for memset, strstr, strcmp #include // for next -#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, mkshort, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, xstrtoi, mkshort_del_handle, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa... +#include "defs.h" // for Waypoint, warning, route_head, fatal, UrlLink, bounds, UrlList, unknown_alt, xfree, waypt_add_to_bounds, waypt_init_bounds, xstrtoi, route_add_wpt, route_disp_all, waypt_bounds_valid, xmalloc, gb_color, WaypointList, find_wa... #include "formspec.h" // for FormatSpecificDataList #include "garmin_fs.h" // for garmin_fs_t, garmin_ilink_t, garmin_fs_alloc #include "garmin_tables.h" // for gt_waypt_class_map_point, gt_color_index_by_rgb, gt_color_value, gt_waypt_classes_e, gt_find_desc_from_icon_number, gt_find_icon_number_from_desc, gt_gdb_display_mode_symbol, gt_get_icao_country, gt_waypt_class_user_waypoint, GDB, gt_display_mode_symbol #include "gbfile.h" // for gbfgetint32, gbfputint32, gbfgetc, gbfread, gbfwrite, gbfgetdbl, gbfputc, gbfgetcstr, gbfclose, gbfgetnativecstr, gbfopen_le, gbfputint16, gbfile, gbfcopyfrom, gbfputcstr, gbfrewind, gbfseek, gbftell, gbfgetcstr_old, gbfgetint16, gbfgetuint32, gbfputdbl #include "grtcirc.h" // for RAD, gcdist, radtometers #include "jeeps/gpsmath.h" // for GPS_Math_Deg_To_Semi, GPS_Math_Semi_To_Deg +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime @@ -1113,19 +1114,17 @@ GdbFormat::read() void GdbFormat::reset_short_handle(const char* defname) { - if (short_h != nullptr) { - mkshort_del_handle(&short_h); - } + delete short_h; - short_h = mkshort_new_handle(); + short_h = new MakeShort; - setshort_length(short_h, kGDBNameBufferLen); - setshort_badchars(short_h, "\r\n\t"); - setshort_mustupper(short_h, 0); - setshort_mustuniq(short_h, 1); - setshort_whitespace_ok(short_h, 1); - setshort_repeating_whitespace_ok(short_h, 1); - setshort_defname(short_h, defname); + short_h->set_length(kGDBNameBufferLen); + short_h->set_badchars("\r\n\t"); + short_h->set_mustupper(false); + short_h->set_mustuniq(true); + short_h->set_whitespace_ok(true); + short_h->set_repeating_whitespace_ok(true); + short_h->set_defname(defname); } /* ----------------------------------------------------------------------------*/ @@ -1613,7 +1612,7 @@ GdbFormat::write_waypoint_cb(const Waypoint* refpt) } } - name = mkshort(short_h, name); + name = short_h->mkshort(name); wpt->extra_data = new QString(name); write_waypoint(wpt, name, gmsd, icon, display); @@ -1630,9 +1629,9 @@ GdbFormat::write_route_cb(const route_head* rte) QString name; if (rte->rte_name.isNull()) { - name = mkshort(short_h, QString::asprintf("Route%04d", rte->rte_num)); + name = short_h->mkshort(QString::asprintf("Route%04d", rte->rte_num)); } else { - name = mkshort(short_h, rte->rte_name); + name = short_h->mkshort(rte->rte_name); } rte_ct++; /* increase informational number of written routes */ @@ -1652,9 +1651,9 @@ GdbFormat::write_track_cb(const route_head* trk) QString name; if (trk->rte_name.isNull()) { - name = mkshort(short_h, QString::asprintf("Track%04d", trk->rte_num)); + name = short_h->mkshort(QString::asprintf("Track%04d", trk->rte_num)); } else { - name = mkshort(short_h, trk->rte_name); + name = short_h->mkshort(trk->rte_name); } trk_ct++; /* increase informational number of written tracks */ @@ -1704,7 +1703,8 @@ GdbFormat::wr_deinit() { disp_summary(fout); gdb_flush_waypt_queue(waypt_nameposn_out_hash); - mkshort_del_handle(&short_h); + delete short_h; + short_h = nullptr; gbfclose(fout); gbfclose(ftmp); } diff --git a/gdb.h b/gdb.h index b418a51a1..1e30b7b6c 100644 --- a/gdb.h +++ b/gdb.h @@ -32,11 +32,12 @@ #include // for QVector #include // for QT_VERSION, QT_VERSION_CHECK -#include "defs.h" // for arglist_t, Waypoint, route_head, ARGTYPE_BOOL, ARGTYPE_INT, ARG_NOMINMAX, bounds, FF_CAP_RW_ALL, ff_cap, ff_type, ff_type_file, short_handle +#include "defs.h" // for arglist_t, Waypoint, route_head, ARGTYPE_BOOL, ARGTYPE_INT, ARG_NOMINMAX, bounds, FF_CAP_RW_ALL, ff_cap, ff_type, ff_type_file #include "format.h" // for Format #include "garmin_fs.h" // for garmin_fs_t #include "garmin_tables.h" // for gt_waypt_classes_e #include "gbfile.h" // for gbfile +#include "mkshort.h" // for MakeShort class GdbFormat : public Format @@ -172,7 +173,7 @@ private: WptNamePosnHash waypt_nameposn_in_hidden_hash; WptNameHash waypt_name_in_hidden_hash; WptNamePosnHash waypt_nameposn_out_hash; - short_handle short_h{}; + MakeShort* short_h{}; char* gdb_opt_category{}; char* gdb_opt_ver{}; diff --git a/gpx.cc b/gpx.cc index 4e591b33e..6d0a4c042 100644 --- a/gpx.cc +++ b/gpx.cc @@ -49,6 +49,7 @@ #include "garmin_fs.h" // for garmin_fs_xml_convert, garmin_fs_xml_fprint, GMSD_FIND #include "garmin_tables.h" // for gt_color_index_by_rgb, gt_color_name, gt_color_value_by_name #include "geocache.h" // for Geocache, Geocache::UtfSt... +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime #include "src/core/file.h" // for File #include "src/core/logging.h" // for Warning, Fatal @@ -90,17 +91,15 @@ inline QString GpxFormat::toString(float f) void GpxFormat::gpx_reset_short_handle() { - if (mkshort_handle != nullptr) { - mkshort_del_handle(&mkshort_handle); - } + delete mkshort_handle; - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; if (suppresswhite) { - setshort_whitespace_ok(mkshort_handle, 0); + mkshort_handle->set_whitespace_ok(false); } - setshort_length(mkshort_handle, xstrtoi(snlen, nullptr, 10)); + mkshort_handle->set_length(xstrtoi(snlen, nullptr, 10)); } void @@ -971,7 +970,8 @@ GpxFormat::wr_deinit() delete oqfile; oqfile = nullptr; - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; } QString @@ -1323,7 +1323,7 @@ GpxFormat::gpx_waypt_pr(const Waypoint* waypointp) const writer->writeAttribute(QStringLiteral("lon"), toString(waypointp->longitude)); QString oname = global_opts.synthesize_shortnames ? - mkshort_from_wpt(mkshort_handle, waypointp) : + mkshort_handle->mkshort_from_wpt(waypointp) : waypointp->shortname; gpx_write_common_position(waypointp, gpxpt_waypoint); gpx_write_common_description(waypointp, oname); @@ -1402,7 +1402,7 @@ GpxFormat::gpx_track_disp(const Waypoint* waypointp) const gpx_write_common_position(waypointp, gpxpt_track); QString oname = global_opts.synthesize_shortnames ? - mkshort_from_wpt(mkshort_handle, waypointp) : + mkshort_handle->mkshort_from_wpt(waypointp) : waypointp->shortname; gpx_write_common_description(waypointp, waypointp->wpt_flags.shortname_is_synthetic ? @@ -1491,7 +1491,7 @@ GpxFormat::gpx_route_disp(const Waypoint* waypointp) const writer->writeAttribute(QStringLiteral("lon"), toString(waypointp->longitude)); QString oname = global_opts.synthesize_shortnames ? - mkshort_from_wpt(mkshort_handle, waypointp) : + mkshort_handle->mkshort_from_wpt(waypointp) : waypointp->shortname; gpx_write_common_position(waypointp, gpxpt_route); gpx_write_common_description(waypointp, oname); diff --git a/gpx.h b/gpx.h index f02da3b21..1fd5b9692 100644 --- a/gpx.h +++ b/gpx.h @@ -34,6 +34,7 @@ #include "defs.h" #include "format.h" // for Format #include "formspec.h" // for FormatSpecificData +#include "mkshort.h" // for MakeShort #include "src/core/file.h" // for File #include "src/core/xmlstreamwriter.h" // for XmlStreamWriter #include "src/core/xmltag.h" // for xml_tag @@ -243,7 +244,7 @@ private: gpsbabel::File* iqfile{}; gpsbabel::File* oqfile{}; gpsbabel::XmlStreamWriter* writer{}; - short_handle mkshort_handle{}; + MakeShort* mkshort_handle{}; QString link_url; QString link_text; QString link_type; diff --git a/html.cc b/html.cc index 54ca38428..3273a1d96 100644 --- a/html.cc +++ b/html.cc @@ -33,6 +33,7 @@ #include "formspec.h" // for FormatSpecificDataList, kFsGpx #include "geocache.h" // for Geocache, Geocache::UtfString #include "jeeps/gpsmath.h" // for GPS_Math_WGS84_To_UTM_EN +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime #include "src/core/textstream.h" // for TextStream #include "src/core/xmltag.h" // for xml_findfirst, xml_tag, xml_attribute, fs_xml, xml_findnext @@ -45,7 +46,7 @@ HtmlFormat::wr_init(const QString& fname) { file_out = new gpsbabel::TextStream; file_out->open(fname, QIODevice::WriteOnly, MYNAME); - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; } void @@ -54,7 +55,8 @@ HtmlFormat::wr_deinit() file_out->close(); delete file_out; file_out = nullptr; - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; } QString HtmlFormat::create_id(int sequence_number) @@ -78,7 +80,7 @@ HtmlFormat::html_disp(const Waypoint* wpt) const *file_out << "

\n"; *file_out << " \n"; - QString sn = global_opts.synthesize_shortnames ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname; + QString sn = global_opts.synthesize_shortnames ? mkshort_handle->mkshort_from_wpt(wpt) : wpt->shortname; *file_out << " \n"; *file_out << "
\n"; *file_out << "

" << sn << " - "; @@ -216,7 +218,7 @@ HtmlFormat::html_index(const Waypoint* wpt) const void HtmlFormat::write() { - setshort_length(mkshort_handle, 6); + mkshort_handle->set_length(6); *file_out << "\n"; *file_out << "\n"; diff --git a/html.h b/html.h index 87ba8c0a9..0e930ba2f 100644 --- a/html.h +++ b/html.h @@ -26,6 +26,7 @@ #include "defs.h" #include "format.h" // for Format +#include "mkshort.h" // for MakeShort #include "src/core/textstream.h" // for TextStream @@ -62,7 +63,7 @@ private: /* Data Members */ gpsbabel::TextStream* file_out{nullptr}; - short_handle mkshort_handle{}; + MakeShort* mkshort_handle{}; int waypoint_number{}; diff --git a/humminbird.cc b/humminbird.cc index 95b4453ed..ea3f2f3a8 100644 --- a/humminbird.cc +++ b/humminbird.cc @@ -29,7 +29,8 @@ #include // for snprintf, SEEK_SET #include // for strncpy, memcpy, memset -#include "defs.h" // for Waypoint, be_read32, be_read16, be_write32, fatal, xfree, be_write16, route_head, xcalloc, track_add_wpt, xstrndup, mkshort, mkshort_del_handle, mkshort_new_handle, setshort_badchars, setshort_defname, setshort_length, setshort_mustuniq, setshort_... +#include "defs.h" // for Waypoint, be_read32, be_read16, be_write32, fatal, xfree, be_write16, route_head, xcalloc, track_add_wpt, xstrndup +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime @@ -582,33 +583,33 @@ HumminbirdBase::humminbird_wr_init(const QString& fname) { fout_ = gbfopen_be(fname, "wb", MYNAME); - wptname_sh = mkshort_new_handle(); - - setshort_length(wptname_sh, WPT_NAME_LEN - 1); - setshort_badchars(wptname_sh, BAD_CHARS); - setshort_mustupper(wptname_sh, 0); - setshort_mustuniq(wptname_sh, 0); - setshort_whitespace_ok(wptname_sh, 1); - setshort_repeating_whitespace_ok(wptname_sh, 1); - setshort_defname(wptname_sh, "WPT"); - - rtename_sh = mkshort_new_handle(); - setshort_length(rtename_sh, RTE_NAME_LEN - 1); - setshort_badchars(rtename_sh, BAD_CHARS); - setshort_mustupper(rtename_sh, 0); - setshort_mustuniq(rtename_sh, 0); - setshort_whitespace_ok(rtename_sh, 1); - setshort_repeating_whitespace_ok(rtename_sh, 1); - setshort_defname(rtename_sh, "Route"); - - trkname_sh = mkshort_new_handle(); - setshort_length(trkname_sh, RTE_NAME_LEN - 1); - setshort_badchars(trkname_sh, BAD_CHARS); - setshort_mustupper(trkname_sh, 0); - setshort_mustuniq(trkname_sh, 0); - setshort_whitespace_ok(trkname_sh, 1); - setshort_repeating_whitespace_ok(trkname_sh, 1); - setshort_defname(trkname_sh, "Track"); + wptname_sh = new MakeShort; + + wptname_sh->set_length(WPT_NAME_LEN - 1); + wptname_sh->set_badchars(BAD_CHARS); + wptname_sh->set_mustupper(false); + wptname_sh->set_mustuniq(false); + wptname_sh->set_whitespace_ok(true); + wptname_sh->set_repeating_whitespace_ok(true); + wptname_sh->set_defname("WPT"); + + rtename_sh = new MakeShort; + rtename_sh->set_length(RTE_NAME_LEN - 1); + rtename_sh->set_badchars(BAD_CHARS); + rtename_sh->set_mustupper(false); + rtename_sh->set_mustuniq(false); + rtename_sh->set_whitespace_ok(true); + rtename_sh->set_repeating_whitespace_ok(true); + rtename_sh->set_defname("Route"); + + trkname_sh = new MakeShort; + trkname_sh->set_length(RTE_NAME_LEN - 1); + trkname_sh->set_badchars(BAD_CHARS); + trkname_sh->set_mustupper(false); + trkname_sh->set_mustuniq(false); + trkname_sh->set_whitespace_ok(true); + trkname_sh->set_repeating_whitespace_ok(true); + trkname_sh->set_defname("Track"); waypoint_num = 0; rte_num_ = 0; @@ -617,9 +618,12 @@ HumminbirdBase::humminbird_wr_init(const QString& fname) void HumminbirdBase::humminbird_wr_deinit() { - mkshort_del_handle(&wptname_sh); - mkshort_del_handle(&rtename_sh); - mkshort_del_handle(&trkname_sh); + delete wptname_sh; + wptname_sh = nullptr; + delete rtename_sh; + rtename_sh = nullptr; + delete trkname_sh; + trkname_sh = nullptr; gbfclose(fout_); } @@ -666,8 +670,8 @@ HumminbirdFormat::humminbird_write_waypoint(const Waypoint* wpt) be_write32(&hum.north, qRound(north)); QString name = (global_opts.synthesize_shortnames) - ? mkshort_from_wpt(wptname_sh, wpt) - : mkshort(wptname_sh, wpt->shortname); + ? wptname_sh->mkshort_from_wpt(wpt) + : wptname_sh->mkshort(wpt->shortname); memset(&hum.name, 0, sizeof(hum.name)); memcpy(&hum.name, CSTR(name), name.length()); @@ -686,7 +690,7 @@ HumminbirdHTFormat::humminbird_track_head(const route_head* trk) trk_head = (humminbird_trk_header_t*) xcalloc(1, sizeof(humminbird_trk_header_t)); trk_points = (humminbird_trk_point_t*) xcalloc(max_points, sizeof(humminbird_trk_point_t)); - QString name = mkshort(trkname_sh, trk->rte_name); + QString name = trkname_sh->mkshort(trk->rte_name); strncpy(trk_head->name, CSTR(name), sizeof(trk_head->name)-1); be_write16(&trk_head->trk_num, trk->rte_num); } @@ -835,7 +839,7 @@ HumminbirdFormat::humminbird_rte_tail(const route_head* rte) be_write16(&humrte->num, humrte->num); be_write32(&humrte->time, humrte->time); - QString name = mkshort(rtename_sh, rte->rte_name); + QString name = rtename_sh->mkshort(rte->rte_name); strncpy(humrte->name, CSTR(name), sizeof(humrte->name)-1); gbfputuint32(RTE_MAGIC, fout_); diff --git a/humminbird.h b/humminbird.h index 9e7a43bdc..17f0c44c8 100644 --- a/humminbird.h +++ b/humminbird.h @@ -30,6 +30,7 @@ #include "defs.h" // for ff_cap, arglist_t, ff_cap_read, Waypoint, route_head, ff_cap_write, short_handle, ff_type, ff_type_file #include "format.h" // for Format #include "gbfile.h" // for gbfile +#include "mkshort.h" // for MakeShort class HumminbirdBase @@ -102,7 +103,9 @@ protected: gbfile* fin_{}; gbfile* fout_{}; int waypoint_num{}; - short_handle wptname_sh{}, rtename_sh{}, trkname_sh{}; + MakeShort* wptname_sh{}; + MakeShort* rtename_sh{}; + MakeShort* trkname_sh{}; humminbird_rte_t* humrte{}; int rte_num_{}; QMap map; diff --git a/lowranceusr.cc b/lowranceusr.cc index 89a61585b..cbfd1f05c 100644 --- a/lowranceusr.cc +++ b/lowranceusr.cc @@ -342,7 +342,7 @@ void LowranceusrFormat::wr_init(const QString& fname) { file_out = gbfopen_le(fname, "wb", MYNAME); - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; waypt_out_count = 0; writing_version = xstrtoi(opt_wversion, nullptr, 10); if ((writing_version < 2) || (writing_version > 4)) { @@ -356,7 +356,8 @@ void LowranceusrFormat::wr_deinit() { gbfclose(file_out); - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; utf16le_codec = nullptr; delete waypt_table; waypt_table = nullptr; @@ -1284,7 +1285,7 @@ LowranceusrFormat::lowranceusr_waypt_disp(const Waypoint* wpt) const QString name; if ((wpt->shortname.isEmpty()) || global_opts.synthesize_shortnames) { if (!wpt->description.isEmpty() && global_opts.synthesize_shortnames) { - name = mkshort_from_wpt(mkshort_handle, wpt); + name = mkshort_handle->mkshort_from_wpt(wpt); } else if (!wpt->shortname.isEmpty()) { name = wpt->shortname; } else if (!wpt->description.isEmpty()) { @@ -1835,7 +1836,7 @@ LowranceusrFormat::write() { QString buf; - setshort_length(mkshort_handle, 15); + mkshort_handle->set_length(15); gbfputint32(writing_version, file_out); diff --git a/lowranceusr.h b/lowranceusr.h index 6013fdb27..51b4dbeed 100644 --- a/lowranceusr.h +++ b/lowranceusr.h @@ -101,6 +101,7 @@ #include "format.h" #include "formspec.h" // for FsChainFind, FsChainAdd, kFsLowranceusr4, FormatSpecificData #include "gbfile.h" // for gbfgetint32, gbfputint32, gbfputint16, gbfgetc, gbfgetint16, gbfwrite, gbfputc, gbfeof, gbfgetflt, gbfclose, gbfgetdbl, gbfopen_le, gbfputdbl, gbfputs, gbfile, gbfputflt, gbfread, gbfseek +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime @@ -433,7 +434,7 @@ private: gbfile* file_in{}; gbfile* file_out{}; - short_handle mkshort_handle{}; + MakeShort* mkshort_handle{}; route_head* trk_head{}; route_head* rte_head{}; diff --git a/main.cc b/main.cc index 3c20a5d7b..f99f47903 100644 --- a/main.cc +++ b/main.cc @@ -50,6 +50,7 @@ #include "gbversion.h" // for VERSION_SHA #include "inifile.h" // for inifile_done, inifile_init #include "jeeps/gpsmath.h" // for GPS_Lookup_Datum_Index +#include "mkshort.h" // for MakeShort #include "session.h" // for start_session, session_exit, session_init #include "src/core/datetime.h" // for DateTime #include "src/core/file.h" // for File @@ -213,14 +214,6 @@ signal_handler(int sig) class FallbackOutput { public: - FallbackOutput() : mkshort_handle(mkshort_new_handle()) {} - // delete copy and move constructors and assignment operators. - // The defaults are not appropriate, and we haven't implemented proper ones. - FallbackOutput(const FallbackOutput&) = delete; - FallbackOutput& operator=(const FallbackOutput&) = delete; - FallbackOutput(FallbackOutput&&) = delete; - FallbackOutput& operator=(FallbackOutput&&) = delete; - ~FallbackOutput() {mkshort_del_handle(&mkshort_handle);} void waypt_disp(const Waypoint* wpt) { @@ -232,7 +225,7 @@ public: if (!wpt->description.isEmpty()) { printf("%s/%s", global_opts.synthesize_shortnames ? - qPrintable(mkshort(mkshort_handle, wpt->description)) : + qPrintable(mkshort_handle.mkshort(wpt->description)) : qPrintable(wpt->shortname), qPrintable(wpt->description)); } @@ -244,7 +237,7 @@ public: } private: - short_handle mkshort_handle; + MakeShort mkshort_handle; }; static void diff --git a/mkshort.cc b/mkshort.cc index 4ad3fc47f..8bf839b41 100644 --- a/mkshort.cc +++ b/mkshort.cc @@ -19,12 +19,13 @@ */ +#include "mkshort.h" + #include // for assert #include // for isspace, isdigit #include // for QByteArray #include // for QChar, QChar::ReplacementCharacter -#include // for QHash, QHash<>::iterator, qHash, QHash<>::size_type #include // for QString #include // for QVector #include // for CaseInsensitive @@ -34,52 +35,9 @@ #include "geocache.h" // for Geocache -#define MYNAME "mkshort" - -static const QByteArray vowels("aeiouAEIOU"); -static constexpr int default_target_len = 8; -static constexpr const char default_badchars[] = "\"$.,'!-"; - -class ShortNameKey; -using ShortNameHash = QHash; -class ShortNameKey -{ -public: - ShortNameKey(const QByteArray& name) : shortname(name) {} /* converting constructor */ - - friend qhash_result_t qHash(const ShortNameKey& key, qhash_result_t seed = 0) noexcept - { - // We hash all strings as upper case. - return qHash(key.shortname.toUpper(), seed); - } - - QByteArray shortname; -}; +const QByteArray MakeShort::vowels = "aeiouAEIOU"; -inline bool operator==(const ShortNameKey& lhs, const ShortNameKey& rhs) noexcept -{ - return lhs.shortname.compare(rhs.shortname, Qt::CaseInsensitive) == 0; -} - -struct mkshort_handle_imp { - int target_len{default_target_len}; - QByteArray badchars{default_badchars}; - QByteArray goodchars; - QByteArray defname{"WPT"}; - ShortNameHash namelist; - - /* Various internal flags */ - bool mustupper{false}; - bool whitespaceok{true}; - bool repeating_whitespaceok{false}; - bool must_uniq{true}; -}; - -struct replacement_t { - QByteArray orig; - QByteArray replacement; -}; -static const QVector replacements = { +const QVector MakeShort::replacements = { {"zero", "0"}, {"one", "1"}, {"two", "2"}, @@ -92,26 +50,18 @@ static const QVector replacements = { {"nine", "9"} }; -short_handle -mkshort_new_handle() +void MakeShort::mkshort_add_to_list(QByteArray& name, bool is_utf8) { - return new mkshort_handle_imp; -} - -static -void -mkshort_add_to_list(mkshort_handle_imp* h, QByteArray& name, bool is_utf8) -{ - while (h->namelist.contains(name)) { - auto& conflictctr = h->namelist[name]; + while (namelist_.contains(name)) { + auto& conflictctr = namelist_[name]; QByteArray suffix("."); suffix.append(QByteArray::number(++conflictctr)); int suffixcnt = suffix.size(); - if (name.size() + suffixcnt <= h->target_len) { + if (name.size() + suffixcnt <= target_len_) { name.append(suffix); - } else if (int keepcnt = h->target_len - suffixcnt; keepcnt >= 0) { + } else if (int keepcnt = target_len_ - suffixcnt; keepcnt >= 0) { if (is_utf8) { QString result = grapheme_truncate(QString::fromUtf8(name), keepcnt); name = result.toUtf8().append(suffix); @@ -124,42 +74,14 @@ mkshort_add_to_list(mkshort_handle_imp* h, QByteArray& name, bool is_utf8) } } - h->namelist.insert(name, 0); -} - -void -mkshort_del_handle(short_handle* h) -{ - if (!h) { - return; - } - - auto* hdr = (mkshort_handle_imp*) *h; - - if (!hdr) { - return; - } - -#if 0 - for (auto it = hdr->namelist.cbegin(), end = hdr->namelist.cend(); it != end; ++it) { - if (global_opts.verbose_status >= 2 && it.value()->conflictctr) { - fprintf(stderr, "%d Output name conflicts: '%s'\n", - it.value()->conflictctr, it.key().shortname.constData()); - } - } -#endif - - delete hdr; - *h = nullptr; + namelist_.insert(name, 0); } /* * This is the stuff that makes me ashamed to be a C programmer... */ -static -bool -delete_last_vowel(int start, QByteArray& iostring) +bool MakeShort::delete_last_vowel(int start, QByteArray& iostring) { /* * Basically implement strrchr. @@ -184,8 +106,7 @@ delete_last_vowel(int start, QByteArray& iostring) * Open the slippery slope of literal replacement. Right now, replacements * are made only at the end of the string. */ -void -replace_constants(QByteArray& s) +void MakeShort::replace_constants(QByteArray& s) { for (const auto& r : replacements) { /* @@ -202,59 +123,50 @@ replace_constants(QByteArray& s) } } - /* * Externally callable function to set the max length of the * strings returned by mkshort(). 0 resets to default. */ -void -setshort_length(short_handle h, int l) +void MakeShort::set_length(int l) { - auto* hdl = (mkshort_handle_imp*) h; if (l < 0) { fatal("mkshort: short length must be non-negative.\n"); } else if (l == 0) { - hdl->target_len = default_target_len; + target_len_ = default_target_len; } else { - hdl->target_len = l; + target_len_ = l; } } /* - * Call with L nonzero if whitespace in the generated shortname is wanted. + * Call with ok = true if whitespace in the generated shortname is wanted. */ -void -setshort_whitespace_ok(short_handle h, int l) +void MakeShort::set_whitespace_ok(bool ok) { - auto* hdl = (mkshort_handle_imp*) h; - hdl->whitespaceok = l; + whitespaceok_ = ok; } /* - * Call with L nonzero if multiple consecutive whitespace in the + * Call with ok = true if multiple consecutive whitespace in the * generated shortname is wanted. */ -void -setshort_repeating_whitespace_ok(short_handle h, int l) +void MakeShort::set_repeating_whitespace_ok(bool ok) { - auto* hdl = (mkshort_handle_imp*) h; - hdl->repeating_whitespaceok = l; + repeating_whitespaceok_ = ok; } /* * Set default name given to a waypoint if no valid is possible * because it was filtered by charsets or null or whatever. */ -void -setshort_defname(short_handle h, const char* s) +void MakeShort::set_defname(const char* s) { - auto* hdl = (mkshort_handle_imp*) h; if (s == nullptr) { - fatal("setshort_defname called without a valid name."); + fatal("set_defname called without a valid name."); } - hdl->defname = s; + defname_ = s; } /* @@ -262,57 +174,45 @@ setshort_defname(short_handle h, const char* s) * that must never appear in a string returned by mkshort. NULL * resets to default. */ -void -setshort_badchars(short_handle h, const char* s) +void MakeShort::set_badchars(const char* s) { - auto* hdl = (mkshort_handle_imp*) h; - - hdl->badchars = s ? s : default_badchars; + badchars_ = (s == nullptr)? default_badchars : s; } /* * Only characters that appear in *s are "whitelisted" to appear * in generated names. */ -void -setshort_goodchars(short_handle h, const char* s) +void MakeShort::set_goodchars(const char* s) { - auto* hdl = (mkshort_handle_imp*) h; - - if (s != nullptr) { - hdl->goodchars = s; + if (s == nullptr) { + goodchars_.clear(); } else { - hdl->goodchars.clear(); + goodchars_ = s; } } /* - * Call with i non-zero if generated names must be uppercase only. + * Call with must = true if generated names must be uppercase only. */ -void -setshort_mustupper(short_handle h, int i) +void MakeShort::set_mustupper(bool must) { - auto* hdl = (mkshort_handle_imp*) h; - hdl->mustupper = i; + mustupper_ = must; } /* - * Call with i zero if the generated names don't have to be unique. + * Call with must = false if the generated names don't have to be unique. * (By default, they are.) */ -void -setshort_mustuniq(short_handle h, int i) +void MakeShort::set_mustuniq(bool must) { - auto* hdl = (mkshort_handle_imp*) h; - hdl->must_uniq = i; + must_uniq_ = must; } -QByteArray -mkshort(short_handle h, const QByteArray& istring, bool is_utf8) +QByteArray MakeShort::mkshort(const QByteArray& istring, bool is_utf8) { QByteArray ostring; - auto* hdl = (mkshort_handle_imp*) h; if (is_utf8) { /* clean UTF-8 string */ @@ -332,7 +232,7 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) * the new seven digit geocache numbers and special case whacking * the 'G' off the front. */ - if ((hdl->target_len == 6) && (ostring.size() == 7) && + if ((target_len_ == 6) && (ostring.size() == 7) && ostring.startsWith("GC")) { ostring.remove(0, 1); } @@ -340,7 +240,7 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) /* * Whack leading "[Tt]he " */ - if ((ostring.size() > (hdl->target_len + 4)) && + if ((ostring.size() > (target_len_ + 4)) && (ostring.startsWith("The ") || ostring.startsWith("the "))) { ostring.remove(0, 4); } @@ -348,7 +248,7 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) /* In all cases eliminate leading and trailing whitespace */ ostring = ostring.trimmed(); - if (!hdl->whitespaceok) { + if (!whitespaceok_) { /* * Eliminate Whitespace */ @@ -361,7 +261,7 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) } } - if (hdl->mustupper) { + if (mustupper_) { ostring = ostring.toUpper(); } @@ -378,10 +278,10 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) QByteArray tstring; ostring.swap(tstring); for (const auto ch : qAsConst(tstring)) { - if (hdl->badchars.contains(ch)) { + if (badchars_.contains(ch)) { continue; } - if (!hdl->goodchars.isEmpty() && (!hdl->goodchars.contains(ch))) { + if (!goodchars_.isEmpty() && (!goodchars_.contains(ch))) { continue; } ostring.append(ch); @@ -395,7 +295,7 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) * operations that removed character(s) before and/or after whitespace. * Conditionally simplify embedded whitespace. */ - ostring = hdl->repeating_whitespaceok? ostring.trimmed() : ostring.simplified(); + ostring = repeating_whitespaceok_? ostring.trimmed() : ostring.simplified(); /* * Toss vowels to approach target length, but don't toss them @@ -414,9 +314,9 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) * * It also helps units with speech synthesis. */ - bool replaced = hdl->target_len < 15; + bool replaced = target_len_ < 15; - while (replaced && (ostring.size() > hdl->target_len)) { + while (replaced && (ostring.size() > target_len_)) { replaced = delete_last_vowel(2, ostring); } @@ -433,18 +333,18 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) * If the numeric component alone is longer than our target string * length, use the trailing part of the the numeric component. */ - if (int delcnt = ostring.size() - hdl->target_len; delcnt > 0) { + if (int delcnt = ostring.size() - target_len_; delcnt > 0) { int suffixcnt = 0; for (auto it = ostring.crbegin(); it != ostring.crend(); ++it) { if (isdigit(*it)) { ++suffixcnt; } - if (suffixcnt == hdl->target_len) { + if (suffixcnt == target_len_) { break; } } - int keepcnt = hdl->target_len - suffixcnt; + int keepcnt = target_len_ - suffixcnt; assert(keepcnt >= 0); if (is_utf8) { @@ -463,27 +363,25 @@ mkshort(short_handle h, const QByteArray& istring, bool is_utf8) * let the must_uniq code handle it. */ if (ostring.isEmpty()) { - ostring = hdl->defname; + ostring = defname_; } - if (hdl->must_uniq) { - mkshort_add_to_list(hdl, ostring, is_utf8); + if (must_uniq_) { + mkshort_add_to_list(ostring, is_utf8); } return ostring; } -QString -mkshort(short_handle h, const QString& istring) +QString MakeShort::mkshort(const QString& istring) { - return mkshort(h, istring.toUtf8(), true); + return mkshort(istring.toUtf8(), true); } /* * As above, but arg list is a waypoint so we can centralize * the code that considers the alternate sources. */ -QString -mkshort_from_wpt(short_handle h, const Waypoint* wpt) +QString MakeShort::mkshort_from_wpt(const Waypoint* wpt) { /* This probably came from a Groundspeak Pocket Query * so use the 'cache name' instead of the description field @@ -492,20 +390,20 @@ mkshort_from_wpt(short_handle h, const Waypoint* wpt) */ if (wpt->gc_data->diff && wpt->gc_data->terr && !wpt->notes.isEmpty()) { - return mkshort(h, wpt->notes); + return mkshort(wpt->notes); } if (!wpt->description.isEmpty()) { - return mkshort(h, wpt->description); + return mkshort(wpt->description); } if (!wpt->notes.isEmpty()) { - return mkshort(h, wpt->notes); + return mkshort(wpt->notes); } /* Should probably never actually happen... */ /* O.K.: But this can happen (waypoints transformed from trackpoints )! */ /* Now we return every time a valid entity." */ - return mkshort(h, wpt->shortname); + return mkshort(wpt->shortname); } diff --git a/mkshort.h b/mkshort.h new file mode 100644 index 000000000..a672a0d48 --- /dev/null +++ b/mkshort.h @@ -0,0 +1,109 @@ +/* + Generate unique short names. + + Copyright (C) 2003-2006, 2023 Robert Lipe, robertlipe+source@gpsbabel.org + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + */ + +#ifndef MKSHORT_H_INCLUDED_ +#define MKSHORT_H_INCLUDED_ + +#include // for QByteArray +#include // for QHash, QHash<>::iterator, qHash, QHash<>::size_type +#include // for QString +#include // for QVector +#include // for CaseInsensitive + +#include "defs.h" + + +class MakeShort +{ +public: + + /* Member Functions */ + + void set_length(int l); + void set_whitespace_ok(bool ok); + void set_repeating_whitespace_ok(bool ok); + void set_defname(const char* s); + void set_badchars(const char* s); + void set_goodchars(const char* s); + void set_mustupper(bool must); + void set_mustuniq(bool must); + QByteArray mkshort(const QByteArray& istring, bool is_utf8); + QString mkshort(const QString& istring); + QString mkshort_from_wpt(const Waypoint* wpt); + +private: + + /* Types */ + + class ShortNameKey; + using ShortNameHash = QHash; + class ShortNameKey + { + public: + ShortNameKey(const QByteArray& name) : shortname(name) {} /* converting constructor */ + + friend qhash_result_t qHash(const ShortNameKey& key, qhash_result_t seed = 0) noexcept + { + // We hash all strings as upper case. + return qHash(key.shortname.toUpper(), seed); + } + bool operator==(const ShortNameKey& other) const + { + return shortname.compare(other.shortname, Qt::CaseInsensitive) == 0; + } + + private: + QByteArray shortname; + }; + + struct replacement_t { + QByteArray orig; + QByteArray replacement; + }; + + /* Constants */ + + static const QByteArray vowels; + static constexpr int default_target_len = 8; + static constexpr const char default_badchars[] = "\"$.,'!-"; + static const QVector replacements; + + /* Member Functions */ + + void mkshort_add_to_list(QByteArray& name, bool is_utf8); + static bool delete_last_vowel(int start, QByteArray& iostring); + static void replace_constants(QByteArray& s); + + /* Data Members */ + + int target_len_{default_target_len}; + QByteArray badchars_{default_badchars}; + QByteArray goodchars_; + QByteArray defname_{"WPT"}; + ShortNameHash namelist_; + + /* Various internal flags */ + bool mustupper_{false}; + bool whitespaceok_{true}; + bool repeating_whitespaceok_{false}; + bool must_uniq_{true}; +}; +#endif // MKSHORT_H_INCLUDED_ diff --git a/nmea.cc b/nmea.cc index 442d5857a..84129cd0a 100644 --- a/nmea.cc +++ b/nmea.cc @@ -45,6 +45,7 @@ #include "gbfile.h" // for gbfprintf, gbfflush, gbfclose, gbfopen, gbfgetstr, gbfile #include "gbser.h" // for gbser_set_speed, gbser_flush, gbser_read_line, gbser_deinit, gbser_init, gbser_write #include "jeeps/gpsmath.h" // for GPS_Lookup_Datum_Index, GPS_Math_Known_Datum_To_WGS84_M +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime #include "src/core/logging.h" // for Warning @@ -299,8 +300,8 @@ NmeaFormat::wr_init(const QString& fname) } } - mkshort_handle = mkshort_new_handle(); - setshort_length(mkshort_handle, xstrtoi(snlenopt, nullptr, 10)); + mkshort_handle = new MakeShort; + mkshort_handle->set_length(xstrtoi(snlenopt, nullptr, 10)); if (opt_gisteq) { opt_gpgga = nullptr; @@ -313,7 +314,8 @@ void NmeaFormat::wr_deinit() { gbfclose(file_out); - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; } void @@ -1164,9 +1166,9 @@ NmeaFormat::nmea_wayptpr(const Waypoint* wpt) const double lat = degrees2ddmm(wpt->latitude); double lon = degrees2ddmm(wpt->longitude); if (global_opts.synthesize_shortnames) { - s = mkshort_from_wpt(mkshort_handle, wpt); + s = mkshort_handle->mkshort_from_wpt(wpt); } else { - s = mkshort(mkshort_handle, wpt->shortname); + s = mkshort_handle->mkshort(wpt->shortname); } snprintf(obuf, sizeof(obuf), "GPWPL,%08.3f,%c,%09.3f,%c,%s", diff --git a/nmea.h b/nmea.h index d612abdbb..e265f051b 100644 --- a/nmea.h +++ b/nmea.h @@ -33,6 +33,7 @@ #include "defs.h" #include "format.h" // for Format #include "gbfile.h" // for gbfile +#include "mkshort.h" // for MakeShort class NmeaFormat : public Format @@ -121,7 +122,7 @@ private: gbfile* file_in{}, *file_out{}; route_head* trk_head{}; - short_handle mkshort_handle{}; + MakeShort* mkshort_handle{}; preferred_posn_type posn_type{}; read_mode_type read_mode{}; QDateTime prev_datetime; diff --git a/ozi.cc b/ozi.cc index 14473ac8a..74e33262a 100644 --- a/ozi.cc +++ b/ozi.cc @@ -55,6 +55,7 @@ #include "csv_util.h" // for csv_stringclean #include "formspec.h" // for FsChainAdd, FsChainFind, kFsOzi, FormatSpecificData #include "jeeps/gpsmath.h" // for GPS_Math_Known_Datum_To_WGS84_M +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime #include "src/core/textstream.h" // for TextStream @@ -77,7 +78,7 @@ struct ozi_fsdata : FormatSpecificData { static gpsbabel::TextStream* stream = nullptr; -static short_handle mkshort_handle; +static MakeShort* mkshort_handle; static route_head* trk_head; static route_head* rte_head; @@ -437,7 +438,6 @@ rd_init(const QString& fname) { ozi_open_io(fname, QFile::ReadOnly); - mkshort_handle = mkshort_new_handle(); ozi_init_units(0); } @@ -445,8 +445,6 @@ static void rd_deinit() { ozi_close_io(); - - mkshort_del_handle(&mkshort_handle); } static void @@ -460,26 +458,26 @@ wr_init(const QString& fname) ozi_ofname = fname; - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; /* set mkshort options from the command line if applicable */ if (global_opts.synthesize_shortnames) { - setshort_length(mkshort_handle, xstrtoi(snlenopt, nullptr, 10)); + mkshort_handle->set_length(xstrtoi(snlenopt, nullptr, 10)); if (snwhiteopt) { - setshort_whitespace_ok(mkshort_handle, xstrtoi(snwhiteopt, nullptr, 10)); + mkshort_handle->set_whitespace_ok(xstrtoi(snwhiteopt, nullptr, 10)); } if (snupperopt) { - setshort_mustupper(mkshort_handle, xstrtoi(snupperopt, nullptr, 10)); + mkshort_handle->set_mustupper(xstrtoi(snupperopt, nullptr, 10)); } if (snuniqueopt) { - setshort_mustuniq(mkshort_handle, xstrtoi(snuniqueopt, nullptr, 10)); + mkshort_handle->set_mustuniq(xstrtoi(snuniqueopt, nullptr, 10)); } - setshort_badchars(mkshort_handle, "\","); + mkshort_handle->set_badchars("\","); } ozi_init_units(1); @@ -492,7 +490,8 @@ wr_deinit() ozi_close_io(); ozi_ofname.clear(); - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; } static void @@ -881,7 +880,7 @@ ozi_waypt_pr(const Waypoint* wpt) if ((wpt->shortname.isEmpty()) || (global_opts.synthesize_shortnames)) { if (!wpt->description.isEmpty()) { if (global_opts.synthesize_shortnames) { - shortname = mkshort_from_wpt(mkshort_handle, wpt); + shortname = mkshort_handle->mkshort_from_wpt(wpt); } else { shortname = csv_stringclean(wpt->description, BADCHARS); } diff --git a/text.cc b/text.cc index b582abf5e..e4ed37892 100644 --- a/text.cc +++ b/text.cc @@ -48,7 +48,7 @@ TextFormat::wr_init(const QString& fname) file_out = new gpsbabel::TextStream; file_out->open(fname, QIODevice::WriteOnly, MYNAME); } - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; } void @@ -59,7 +59,8 @@ TextFormat::wr_deinit() delete file_out; file_out = nullptr; } - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; + mkshort_handle = nullptr; output_name.clear(); } @@ -90,7 +91,7 @@ TextFormat::text_disp(const Waypoint* wpt) if (wpt->altitude != unknown_alt) { position += QStringLiteral(" alt:%1").arg((int)((altunits[0]=='f') ? METERS_TO_FEET(wpt->altitude) : wpt->altitude)); } - QString sn = global_opts.synthesize_shortnames ? mkshort_from_wpt(mkshort_handle, wpt) : wpt->shortname; + QString sn = global_opts.synthesize_shortnames ? mkshort_handle->mkshort_from_wpt(wpt) : wpt->shortname; *file_out << sn.leftJustified(16) << " " << position.rightJustified(59) << "\n"; if (wpt->description != wpt->shortname) { @@ -196,7 +197,7 @@ TextFormat::write() if (!suppresssep && !split_output) { *file_out << "-----------------------------------------------------------------------------\n"; } - setshort_length(mkshort_handle, 6); + mkshort_handle->set_length(6); auto text_disp_lambda = [this](const Waypoint* waypointp)->void { text_disp(waypointp); }; diff --git a/text.h b/text.h index 3305a92b0..37ad2b97d 100644 --- a/text.h +++ b/text.h @@ -26,6 +26,7 @@ #include "defs.h" #include "format.h" // for Format +#include "mkshort.h" // for MakeShort #include "src/core/textstream.h" // for TextStream @@ -60,7 +61,7 @@ private: /* Data Members */ gpsbabel::TextStream* file_out{nullptr}; - short_handle mkshort_handle{}; + MakeShort* mkshort_handle{}; char* suppresssep = nullptr; char* txt_encrypt = nullptr; diff --git a/tpg.cc b/tpg.cc index 4e1e337ba..615a08de2 100644 --- a/tpg.cc +++ b/tpg.cc @@ -32,6 +32,7 @@ #include "defs.h" #include "gbfile.h" // for gbfwrite, gbfgetint16, gbfputint16, gbfclose #include "jeeps/gpsmath.h" // for GPS_Lookup_Datum_Index, GPS_Math_Known_Da... +#include "mkshort.h" // for MakeShort #define MYNAME "TPG" @@ -41,7 +42,7 @@ static gbfile* tpg_file_in; static gbfile* tpg_file_out; -static short_handle mkshort_handle; +static MakeShort* mkshort_handle; static char* tpg_datum_opt; static int tpg_datum_idx; @@ -94,14 +95,14 @@ tpg_wr_init(const QString& fname) { tpg_common_init(); tpg_file_out = gbfopen_le(fname, "wb", MYNAME); - mkshort_handle = mkshort_new_handle(); + mkshort_handle = new MakeShort; waypt_out_count = 0; } static void tpg_wr_deinit() { - mkshort_del_handle(&mkshort_handle); + delete mkshort_handle; gbfclose(tpg_file_out); } @@ -188,7 +189,7 @@ tpg_waypt_pr(const Waypoint* wpt) if ((wpt->shortname.isEmpty()) || (global_opts.synthesize_shortnames)) { if (!wpt->description.isEmpty()) { if (global_opts.synthesize_shortnames) { - shortname = mkshort_from_wpt(mkshort_handle, wpt); + shortname = mkshort_handle->mkshort_from_wpt(wpt); } else { shortname = wpt->description; } @@ -291,9 +292,9 @@ tpg_write() int s = waypt_count(); if (global_opts.synthesize_shortnames) { - setshort_length(mkshort_handle, 32); - setshort_whitespace_ok(mkshort_handle, 1); - setshort_mustupper(mkshort_handle, 1); + mkshort_handle->set_length(32); + mkshort_handle->set_whitespace_ok(true); + mkshort_handle->set_mustupper(true); } if (s > MAXTPGOUTPUTPINS) { diff --git a/vcf.cc b/vcf.cc index ee48acbdf..fd3e90844 100644 --- a/vcf.cc +++ b/vcf.cc @@ -31,7 +31,6 @@ static gbfile* file_out; -static short_handle mkshort_handle; static char* vcf_encrypt = nullptr; @@ -49,14 +48,12 @@ static void wr_init(const QString& fname) { file_out = gbfopen(fname, "w", MYNAME); - mkshort_handle = mkshort_new_handle(); } static void wr_deinit() { gbfclose(file_out); - mkshort_del_handle(&mkshort_handle); } /* @@ -132,7 +129,6 @@ vcf_disp(const Waypoint* wpt) static void data_write() { - setshort_length(mkshort_handle, 6); waypt_disp_all(vcf_disp); } diff --git a/xcsv.cc b/xcsv.cc index fa7e6dbdc..2794c0f7d 100644 --- a/xcsv.cc +++ b/xcsv.cc @@ -1013,7 +1013,7 @@ XcsvFormat::xcsv_waypt_pr(const Waypoint* wpt) if (wpt->shortname.isEmpty() || global_opts.synthesize_shortnames) { if (!wpt->description.isEmpty()) { if (global_opts.synthesize_shortnames) { - shortname = mkshort_from_wpt(xcsv_file->mkshort_handle, wpt); + shortname = xcsv_file->mkshort_handle.mkshort_from_wpt(wpt); } else { shortname = csv_stringclean(wpt->description, xcsv_style->badchars); } @@ -1091,10 +1091,10 @@ XcsvFormat::xcsv_waypt_pr(const Waypoint* wpt) case XcsvStyle::XT_ANYNAME: { QString anyname = wpt->shortname; if (anyname.isEmpty()) { - anyname = mkshort(xcsv_file->mkshort_handle, wpt->description); + anyname = xcsv_file->mkshort_handle.mkshort(wpt->description); } if (anyname.isEmpty()) { - anyname = mkshort(xcsv_file->mkshort_handle, wpt->description); + anyname = xcsv_file->mkshort_handle.mkshort(wpt->description); } if (anyname.isEmpty()) { anyname = wpt->notes; @@ -1954,32 +1954,32 @@ XcsvFormat::wr_init(const QString& fname) xcsv_file->fname = fname; if (xcsv_style->shortlen) { - setshort_length(xcsv_file->mkshort_handle, *xcsv_style->shortlen); + xcsv_file->mkshort_handle.set_length(*xcsv_style->shortlen); } if (xcsv_style->whitespace_ok) { - setshort_whitespace_ok(xcsv_file->mkshort_handle, *xcsv_style->whitespace_ok); + xcsv_file->mkshort_handle.set_whitespace_ok(*xcsv_style->whitespace_ok); } /* set mkshort options from the command line */ if (global_opts.synthesize_shortnames) { if (snlenopt) { - setshort_length(xcsv_file->mkshort_handle, xstrtoi(snlenopt, nullptr, 10)); + xcsv_file->mkshort_handle.set_length(xstrtoi(snlenopt, nullptr, 10)); } if (snwhiteopt) { - setshort_whitespace_ok(xcsv_file->mkshort_handle, xstrtoi(snwhiteopt, nullptr, 10)); + xcsv_file->mkshort_handle.set_whitespace_ok(xstrtoi(snwhiteopt, nullptr, 10)); } if (snupperopt) { - setshort_mustupper(xcsv_file->mkshort_handle, xstrtoi(snupperopt, nullptr, 10)); + xcsv_file->mkshort_handle.set_mustupper(xstrtoi(snupperopt, nullptr, 10)); } if (snuniqueopt) { - setshort_mustuniq(xcsv_file->mkshort_handle, xstrtoi(snuniqueopt, nullptr, 10)); + xcsv_file->mkshort_handle.set_mustuniq(xstrtoi(snuniqueopt, nullptr, 10)); } - setshort_badchars(xcsv_file->mkshort_handle, CSTR(xcsv_style->badchars)); + xcsv_file->mkshort_handle.set_badchars(CSTR(xcsv_style->badchars)); } diff --git a/xcsv.h b/xcsv.h index 0cbfd1345..3a586c0c5 100644 --- a/xcsv.h +++ b/xcsv.h @@ -37,8 +37,9 @@ #include // for qRound64 #include "defs.h" -#include "format.h" -#include "garmin_fs.h" +#include "format.h" // for Format +#include "garmin_fs.h" // for garmin_fs_t +#include "mkshort.h" // for MakeShort #include "src/core/datetime.h" // for DateTime #include "src/core/textstream.h" // for TextStream @@ -239,7 +240,7 @@ public: std::optional shortlen; /* SHORTWHITE from style file */ - std::optional whitespace_ok; + std::optional whitespace_ok; private: /* Types */ @@ -298,28 +299,13 @@ private: class XcsvFile { public: - /* Special Member Functions */ - - XcsvFile() : mkshort_handle(mkshort_new_handle()) {} - // delete copy and move constructors and assignment operators. - // The defaults are not appropriate, and we haven't implemented proper ones. - XcsvFile(const XcsvFile&) = delete; - XcsvFile& operator=(const XcsvFile&) = delete; - XcsvFile(XcsvFile&&) = delete; - XcsvFile& operator=(XcsvFile&&) = delete; - ~XcsvFile() - { - if (mkshort_handle != nullptr) { - mkshort_del_handle(&mkshort_handle); - } - } /* Data Members */ gpsbabel::TextStream stream; QString fname; int gps_datum_idx{-1}; /* result of GPS_Lookup_Datum_Index */ - short_handle mkshort_handle{nullptr}; + MakeShort mkshort_handle; }; struct xcsv_parse_data { -- 2.30.2